// HDB3编码器
/*
将输出编码设置为二进制
1:11
0:00
-1:01
1:10
0:01
-1:00
0--00，1--01，B--10，V--11
https://blog.csdn.net/DengFengLai123/article/details/79674063?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-0.no_search_link&spm=1001.2101.3001.4242.1
先将输入的信号序列转换成AMI码
*/
module HDB3_encoder (
    clk,rst_n,code_out,code_in,
    V_code_TP,BV_code_TP
);

input  wire clk,rst_n,code_in;
output wire [1:0] code_out;
output reg V_code_TP,BV_code_TP;

reg [1:0] AMI_code;
// reg cnt_1;// 记1的个数
reg [1:0] V_code,B_code,AMI_BV_code,next_V;
reg [2:0] cnt_zero;// 记0的个数
reg cnt_01;// 用来判断两个相邻的V之间的01是否为偶数
reg [1:0] buffer_1,buffer_2,buffer_3;
reg first_V;// 判断是否为第一个V
reg cnt_AMI;// 记非零，转AMI用
reg stage;

parameter one_pos = 2'b01,zero_out = 2'b00,one_neg = 2'b10;
parameter zero = 2'b00,one = 2'b01,B = 2'b10,V = 2'b11;

assign code_out = AMI_BV_code;

always @(posedge clk) begin
    V_code_TP <= (B_code == V)? 1'b1 : 1'b0;
    BV_code_TP <= (B_code == B)? 1'b1 : 1'b0 || (B_code == V)? 1'b1 : 1'b0 || (B_code == one)? 1'b1 : 1'b0;
end


// code_in to V_code
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        // code_out <= 2'b01;
        // AMI_code <= 2'b01;
        // cnt_1 <= 0;
        V_code <= zero;
        cnt_zero <= 0;
    end
    else if(code_in == 0) begin
        if (cnt_zero == 3) begin
            cnt_zero <= 0;
            V_code <= V;
        end
        else begin
            cnt_zero <= cnt_zero + 1;
            V_code <= zero;
        end
    end 
    else begin
        cnt_zero <= 0;
        V_code <= one;
    end

end

// 对V_code进行延时三个周期的延时处理
always @(posedge clk) begin
    buffer_1 <= V_code;
    buffer_2 <= buffer_1;
    buffer_3 <= buffer_2;
end

// add B_code
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin // rst_n下降沿触发重置函数
        B_code <= 0;
        cnt_01 <= 0;
        first_V <= 0;
    end
    else begin// 函数位置
        if (V_code == V & first_V == 1) begin// 第二个V信号执行
            cnt_01 <= 0;// 非阻塞型赋值不会影响到后面对当前状态的判断

            if (cnt_01 == 0) begin// 判断cnt_01是否为0,若为0则进行加B
                B_code <= B;
            end
            else begin
                B_code <= buffer_3;
            end

        end
        else if (V_code == V & first_V == 0) begin// 第一个V信号置first_V为1，不进行后续判断
            first_V <= 1;
            B_code <= buffer_3;
        end
        else begin
            B_code <= buffer_3;
            if (V_code == one & first_V == 1) begin
                cnt_01 <= ~cnt_01;
            end
            else begin
                cnt_01 <= cnt_01;
            end
        end
    end
end


always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        AMI_BV_code <= zero_out;
        stage <= 0;
        cnt_AMI <= 0;
    end
    else begin
        
        if (AMI_BV_code != zero_out) begin
            next_V <= AMI_BV_code;
        end
        else
            next_V <= next_V;
        case (B_code)
            zero:begin
                AMI_BV_code <= zero_out;
            end
            one:begin
                // next_V <= one_pos;
                if (cnt_AMI == 0) begin
                    AMI_BV_code <= one_pos;
                    cnt_AMI <= ~cnt_AMI;
                end
                else begin
                    AMI_BV_code <= one_neg;
                    cnt_AMI <= ~cnt_AMI;
                end
            end
            B:begin
                // next_V <= AMI_BV_code;
                if (cnt_AMI == 0) begin
                    AMI_BV_code <= one_pos;
                    cnt_AMI <= ~cnt_AMI;
                end
                else begin
                    AMI_BV_code <= one_neg;
                    cnt_AMI <= ~cnt_AMI;
                end
            end
            V:begin
                AMI_BV_code <= next_V;
            end
            default :
                AMI_BV_code <= zero_out;
        endcase
    end
end


endmodule //HDB3_encode